package top.zywork.service.impl;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.zywork.common.BeanUtils;
import top.zywork.constant.SysMenuConstant;
import top.zywork.dao.*;
import top.zywork.dos.RoleSysMenuDO;
import top.zywork.dto.*;
import top.zywork.query.RoleSysMenuQuery;
import top.zywork.query.UserRoleQuery;
import top.zywork.service.AbstractBaseService;
import top.zywork.service.RoleService;
import top.zywork.service.RoleSysMenuService;
import top.zywork.service.UserRoleService;
import top.zywork.vo.MenuImportExportVO;
import top.zywork.vo.ResponseStatusVO;
import top.zywork.vo.RoleSysMenuVO;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * RoleSysMenuServiceImpl服务接口实现类<br/>
 *
 * 创建于2019-09-25<br/>
 *
 * @author http://zywork.top 危锦辉
 * @version 1.0
 */
@Service(value = "roleSysMenuService")
public class RoleSysMenuServiceImpl extends AbstractBaseService implements RoleSysMenuService {

    private RoleSysMenuDAO roleSysMenuDAO;

    private UserRoleService userRoleService;

    private SysMenuDAO sysMenuDAO;

    private SysMenuMetaDAO sysMenuMetaDAO;

    private RoleDAO roleDAO;


    @Autowired
    public void setRoleSysMenuDAO(RoleSysMenuDAO roleSysMenuDAO) {
        super.setBaseDAO(roleSysMenuDAO);
        this.roleSysMenuDAO = roleSysMenuDAO;
    }

    @Autowired
    public void setRoleService(UserRoleService userRoleService) {
        this.userRoleService = userRoleService;
    }

    @Autowired
    public void setSysMenuDAO(SysMenuDAO sysMenuDAO) {
        this.sysMenuDAO = sysMenuDAO;
    }

    @Autowired
    public void setSysMenuMetaDAO(SysMenuMetaDAO sysMenuMetaDAO) {
        this.sysMenuMetaDAO = sysMenuMetaDAO;
    }

    @Autowired
    public void setRoleDAO(RoleDAO roleDAO) {
        this.roleDAO = roleDAO;
    }

    @PostConstruct
    public void init() {
        super.init(RoleSysMenuDO.class, RoleSysMenuDTO.class);
    }

    @Override
    public ResponseStatusVO listAllByRoleIdArr(Long userId) {
        if (null == userId || userId == 0) {
            return ResponseStatusVO.dataError("用户不存在", null);
        }
        UserRoleQuery userRoleQuery = new UserRoleQuery();
        userRoleQuery.setUserId(userId);
        PagerDTO pagerDTO = userRoleService.listAllByCondition(userRoleQuery);
        List<Object> userRoleObjectList = pagerDTO.getRows();
        int len = userRoleObjectList.size();
        if (null == userRoleObjectList || len <= 0) {
            return ResponseStatusVO.error("该用户未配置角色", null);
        }
        Long[] roleIdArr = new Long[len];
        List<UserRoleDTO> userRoleDTOList = BeanUtils.copy(userRoleObjectList, UserRoleDTO.class);
        for (int i = 0; i < len; i++) {
            UserRoleDTO userRoleDTO = userRoleDTOList.get(i);
            roleIdArr[i] = userRoleDTO.getRoleId();
        }
        List<Object> objectList = roleSysMenuDAO.listAllByRoleIdArr(roleIdArr);
        if (null == objectList || objectList.size() <= 0) {
            return ResponseStatusVO.error("未获取到菜单信息", null);
        }
        List<RoleSysMenuVO> roleSysMenuVOList = BeanUtils.copy(objectList, RoleSysMenuVO.class);
        return ResponseStatusVO.ok("查询成功", roleSysMenuVOList);
    }

    /**
     * 处理菜单数据
     * @param menuImportExportVO
     */
    private SysMenuDTO handleMenuData(MenuImportExportVO menuImportExportVO, int level, Long parentId, int order) {
        SysMenuDTO sysMenuDTO = new SysMenuDTO();
        SysMenuMetaDTO sysMenuMetaDTO = new SysMenuMetaDTO();
        SysMenuMetaDTO meta = menuImportExportVO.getMeta();
        sysMenuDTO.setPath(menuImportExportVO.getPath());
        sysMenuDTO.setName(menuImportExportVO.getName());
        sysMenuDTO.setDescription(meta.getTitle());
        sysMenuDTO.setParentId(parentId);
        sysMenuDTO.setMenuLevel(level);
        sysMenuDTO.setMenuOrder(order+1);
        if (null != menuImportExportVO.getRedirect()) {
            sysMenuDTO.setRedirect(menuImportExportVO.getRedirect());
        }
        if (null != meta.getHref()) {
            sysMenuMetaDTO.setHref(meta.getHref());
            sysMenuDTO.setComponent("null");
        } else {
            sysMenuDTO.setComponent(menuImportExportVO.getComponent());
        }
        // 保存菜单信息，获取到菜单编号
        sysMenuDAO.save(sysMenuDTO);
        Long sysMneuId = sysMenuDTO.getId();
        sysMenuMetaDTO.setId(sysMneuId);
        sysMenuMetaDTO.setIcon(meta.getIcon());
        sysMenuMetaDTO.setTitle(meta.getTitle());

        if (null != meta.getHideInMenu()) {
            sysMenuMetaDTO.setHideInMenu(meta.getHideInMenu());
        }
        if (null != meta.getHideInBread()) {
            sysMenuMetaDTO.setHideInBread(meta.getHideInBread());
        }
        if (null != meta.getNotCache()) {
            sysMenuMetaDTO.setNotCache(meta.getNotCache());
        }
        if (null != meta.getBeforeCloseName()) {
            sysMenuMetaDTO.setBeforeCloseName(meta.getBeforeCloseName());
        }
        if (null != meta.getAccess()) {
            sysMenuMetaDTO.setAccess(meta.getAccess());
        }
        sysMenuMetaDAO.save(sysMenuMetaDTO);
        return sysMenuDTO;
    }

    /**
     * 处理角色菜单信息
     * @param roles 角色数组
     * @param menuId 菜单编号
     * @return
     */
    private List<RoleSysMenuDTO> handleRoleMenu(String[] roles, Long menuId) {
        List<RoleSysMenuDTO> roleSysMenuDTOList = new ArrayList<>();
        for (String role : roles) {
            Long id = roleDAO.getByTitle(role);
            RoleSysMenuDTO roleSysMenuDTO = new RoleSysMenuDTO();
            roleSysMenuDTO.setRoleId(id);
            roleSysMenuDTO.setSysMenuId(menuId);
            roleSysMenuDTOList.add(roleSysMenuDTO);
        }
        return roleSysMenuDTOList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importSysMenu(List<MenuImportExportVO> menuImportExportVOList) {
        // 移除所有菜单
        sysMenuDAO.removeAll();
        // 移除所有菜单配置
        sysMenuMetaDAO.removeAll();
        // 移除所有角色菜单信息
        roleSysMenuDAO.removeAll();
        List<Object> roleSysMenuDTOList = new ArrayList<>();
        // 循环导入的json文件
        for (int i = 0; i < menuImportExportVOList.size(); i++) {
            MenuImportExportVO menuImportExportVO = menuImportExportVOList.get(i);
            SysMenuDTO oneSysMenuDTO = handleMenuData(menuImportExportVO, 1, 0L, i);
            Long oneMenuId = oneSysMenuDTO.getId();
            // 储存菜单编号
            String[] oneMenuRoles = menuImportExportVO.getRoles();
            roleSysMenuDTOList.addAll(handleRoleMenu(oneMenuRoles, oneMenuId));
            List<MenuImportExportVO> twoMenu  = menuImportExportVO.getChildren();
            if (null != twoMenu && twoMenu.size() > 0) {
                // 有二级子菜单
                for (int j = 0; j < twoMenu.size(); j++) {
                    MenuImportExportVO menuImportExportVO1 = twoMenu.get(j);
                    SysMenuDTO twoSysMenuDTO = handleMenuData(menuImportExportVO1, 2, oneMenuId, j);
                    Long twoMenuId = twoSysMenuDTO.getId();
                    // 储存二级菜单编号
                    String[] twoMenuRoles = menuImportExportVO.getRoles();
                    roleSysMenuDTOList.addAll(handleRoleMenu(twoMenuRoles, twoMenuId));
                    List<MenuImportExportVO> threeMenu = menuImportExportVO1.getChildren();
                    if (null != threeMenu && threeMenu.size() > 0) {
                        // 有三级子菜单
                        for (int k = 0; k < threeMenu.size(); k++) {
                            MenuImportExportVO menuImportExportVO2 = threeMenu.get(k);
                            SysMenuDTO threeSysMenuDTO = handleMenuData(menuImportExportVO2, 3, twoMenuId, k);
                            Long threeMenuId = threeSysMenuDTO.getId();
                            // 储存菜单编号
                            String[] threeMenuRoles = menuImportExportVO.getRoles();
                            roleSysMenuDTOList.addAll(handleRoleMenu(threeMenuRoles, threeMenuId));
                        }
                    }
                }
            }
        }
        // 处理完菜单，处理角色菜单
        roleSysMenuDAO.saveBatch(roleSysMenuDTOList);
    }

    @Override
    public List<MenuImportExportVO> exportSysMenu() {
        List<MenuImportExportVO> menuImportExportVOList = new ArrayList<>();
        // 获取到所有的菜单
        List<Object> objectList = roleSysMenuDAO.listAllExport();
        List<RoleSysMenuDTO> RoleSysMenuDTOList = BeanUtils.copy(objectList, RoleSysMenuDTO.class);
        // 定义一级菜单
        List<RoleSysMenuDTO> oneLevelMenu = new ArrayList<>();
        // 定义二级菜单
        List<RoleSysMenuDTO> twoLevelMenu = new ArrayList<>();
        // 定义三级菜单
        List<RoleSysMenuDTO> threeLevelMenu = new ArrayList<>();
        for (RoleSysMenuDTO roleSysMenuDTO : RoleSysMenuDTOList) {
            int menuLevel = roleSysMenuDTO.getSysMenuMenuLevel();
            if (SysMenuConstant.ONE_LEVEL_MENU.intValue() == menuLevel) {
                // 是一级菜单
                oneLevelMenu.add(roleSysMenuDTO);
            } else if (SysMenuConstant.TWO_LEVEL_MENU.intValue() == menuLevel) {
                // 是二级菜单
                twoLevelMenu.add(roleSysMenuDTO);
            } else if (SysMenuConstant.THREE_LEVEL_MENU.intValue() == menuLevel) {
                // 是三级菜单
                threeLevelMenu.add(roleSysMenuDTO);
            }
        }
        for (RoleSysMenuDTO oneMenu : oneLevelMenu) {
            // 循环一级菜单
            MenuImportExportVO oneMenuImportExportVO = encapsulationData(oneMenu);
            // 声明二级菜单列表
            List<MenuImportExportVO> twoMenuChildren = oneMenuImportExportVO.getChildren();
            // 菜单编号
            long oneMenuId = oneMenu.getSysMenuId();
            for (RoleSysMenuDTO twoMenu : twoLevelMenu) {
                // 循环二级菜单
                if (oneMenuId == twoMenu.getSysMenuParentId()) {
                    MenuImportExportVO twoMenuImportExportVO = encapsulationData(twoMenu);
                    long twoMenuId = twoMenu.getSysMenuId();
                    // 定义三级菜单列表
                    List<MenuImportExportVO> threeMenuChildren = twoMenuImportExportVO.getChildren();
                    for (RoleSysMenuDTO threeMenu : threeLevelMenu) {
                        // 循环三级菜单
                        if (twoMenuId == threeMenu.getSysMenuParentId()) {
                            MenuImportExportVO threeMenuImportExportVO = encapsulationData(threeMenu);
                            threeMenuChildren.add(threeMenuImportExportVO);
                        }
                    }
                    twoMenuImportExportVO.setChildren(threeMenuChildren);
                    twoMenuChildren.add(twoMenuImportExportVO);
                }
            }
            oneMenuImportExportVO.setChildren(twoMenuChildren);
            menuImportExportVOList.add(oneMenuImportExportVO);
        }
        return menuImportExportVOList;
    }

    /**
     * 根据菜单数据封装成需要的菜单数据
     * @param sysMenuDTO
     * @return
     */
    private MenuImportExportVO encapsulationData(RoleSysMenuDTO sysMenuDTO) {
        MenuImportExportVO menuImportExportVO = new MenuImportExportVO();
        menuImportExportVO.setPath(sysMenuDTO.getSysMenuPath());
        menuImportExportVO.setName(sysMenuDTO.getSysMenuName());
        if (!"null".equals(sysMenuDTO.getSysMenuComponent())) {
            menuImportExportVO.setComponent(sysMenuDTO.getSysMenuComponent());
        }
        if (StringUtils.isNotEmpty(sysMenuDTO.getSysMenuRedirect())) {
            menuImportExportVO.setRedirect(sysMenuDTO.getSysMenuRedirect());
        }
        SysMenuMetaDTO sysMenuMetaDTO = new SysMenuMetaDTO();
        sysMenuMetaDTO.setTitle(sysMenuDTO.getSysMenuMetaTitle());
        sysMenuMetaDTO.setIcon(sysMenuDTO.getSysMenuMetaIcon());
        if (StringUtils.isNotEmpty(sysMenuDTO.getSysMenuMetaHref())) {
            sysMenuMetaDTO.setHref(sysMenuDTO.getSysMenuMetaHref());
        }
        if (null != sysMenuDTO.getSysMenuMetaHideInBread() && StringUtils.isNotEmpty(sysMenuDTO.getSysMenuMetaHideInBread().toString())) {
            sysMenuMetaDTO.setHideInBread(sysMenuDTO.getSysMenuMetaHideInBread());
        }
        if (null != sysMenuDTO.getSysMenuMetaHideInMenu() && StringUtils.isNotEmpty(sysMenuDTO.getSysMenuMetaHideInMenu().toString())) {
            sysMenuMetaDTO.setHideInMenu(sysMenuDTO.getSysMenuMetaHideInMenu());
        }
        if (null != sysMenuDTO.getSysMenuMetaNotCache() && StringUtils.isNotEmpty(sysMenuDTO.getSysMenuMetaNotCache().toString())) {
            sysMenuMetaDTO.setNotCache(sysMenuDTO.getSysMenuMetaNotCache());
        }
        if (StringUtils.isNotEmpty(sysMenuDTO.getSysMenuMetaAccess())) {
            sysMenuMetaDTO.setAccess(sysMenuDTO.getSysMenuMetaAccess());
        }
        if (StringUtils.isNotEmpty(sysMenuDTO.getSysMenuMetaBeforeCloseName())) {
            sysMenuMetaDTO.setBeforeCloseName(sysMenuDTO.getSysMenuMetaBeforeCloseName());
        }
        menuImportExportVO.setMeta(sysMenuMetaDTO);
        menuImportExportVO.setChildren(new ArrayList<>());
        return menuImportExportVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveBatch(List<Object> dataTransferObjList) {
        roleSysMenuDAO.removeByRoleId(BeanUtils.copy(dataTransferObjList.get(0), RoleSysMenuDTO.class).getRoleId());
        // 移除第一个属性
        dataTransferObjList.remove(0);
        if (dataTransferObjList != null && dataTransferObjList.size() > 0) {
            return roleSysMenuDAO.saveBatch(BeanUtils.copyList(dataTransferObjList, RoleSysMenuDTO.class));
        }
        return 0;
    }
}
